package com.yxlgateway.service.impl;

import com.yxlcommon.common.dto.LikesDTO;
import com.yxlcommon.common.pojo.Likes;
import com.yxlgateway.service.RedisService;
import com.yxlgateway.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author: yxl
 * @since: 2022-04-17
 **/
@Service
@Slf4j
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private LikesServiceImpl likesService;


    @Override
    public void saveLikeToRedis(Long objId, Long userId, Byte type) {
        String likeKey = RedisKeyUtils.getLikeKey("" + objId, ""+userId, "" + type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKE, likeKey,"1");
    }

    @Override
    public void unlikeFromRedis(Long objId, Long userId, Byte type) {
        String likeKey = RedisKeyUtils.getLikeKey(""+objId, ""+userId, ""+type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKE,likeKey,"0");
    }

    @Override
    public void deleteFromRedis(Long objId, Long userId, Byte type) {
        String key = RedisKeyUtils.getLikeKey(""+objId, ""+userId, ""+type);
        redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKE,key);
    }

    @Override
    public Long incrementLikeCount(Long objId, Long userId, Byte type) {
        String key = RedisKeyUtils.getLikeKey(""+objId,""+type);
        String likeKey = RedisKeyUtils.getLikeKey("" + objId,""+userId, ""+type);
        if ("0".equals(redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKE, likeKey))
                || redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKE, likeKey) == null){
            return redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_COUNT, likeKey, 1);
        }
        return 0L;
    }

    @Override
    public void decrementLikedCount(Long objId, Long userId, Byte type) {
        String key = RedisKeyUtils.getLikeKey(""+objId, ""+type);
        String likeKey = RedisKeyUtils.getLikeKey(""+objId,""+userId,""+type);
        if ("1".equals(redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKE, likeKey))){
            redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_COUNT,likeKey,-1);
        }
    }

    @Override
    public List<Likes> getLikeDataFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKE, ScanOptions.NONE);
        List<Likes> list = new ArrayList<>();
        while (cursor.hasNext()){
            Map.Entry<Object, Object> entry = cursor.next();
            String key = (String) entry.getKey();

            String[] split = key.split("::");
            byte status = Byte.parseByte((String) entry.getValue());

            Likes likes = new Likes();
            likes.setObjId(Long.valueOf(split[0]));
            likes.setUserId(Long.valueOf(split[1]));
            likes.setType(Byte.valueOf(split[2]));
            likes.setLikeStatus(status);

            list.add(likes);
        }
        return list;
    }

    @Override
    public Cursor<Map.Entry<Object, Object>> getLikedCountFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_COUNT, ScanOptions.NONE);
        return cursor;
    }

    @Override
    public int getOneInfoCount(Long objId, Byte type) {
        String key = RedisKeyUtils.getLikeKey(""+objId, ""+type);
        return (int) redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_COUNT,key);
    }

    public void saveCountInfo(Long objId, Byte type, Long count){
        String key = RedisKeyUtils.getLikeKey(""+objId, ""+type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_COUNT,key,count);
    }

    //redis挂掉后通过mysql中数据恢复redis
    @Override
    public void saveInfoFromDb2Re(Byte type) {
        LikesDTO likesDTO = new LikesDTO();
        likesDTO.setType(type);
        List<Map<String,Object>> likes = likesService.selectLikeInfoByType(likesDTO);
        if (likes.isEmpty() || likes.equals("")){
            return;
        }

        Iterator<Map<String,Object>> it = likes.listIterator();
        while (it.hasNext()){
            Map<String,Object> map = it.next();
            Long objId = (Long) map.get("objId");
            Long count = Long.parseLong(map.get("num_likes").toString());
            saveCountInfo(objId,type,count);
        }
    }


}
